﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Auth;
using Microsoft.WindowsAzure.Storage.Blob;

namespace PetesAzureChinaBlobTool
{
    class Program
    {
        const string usage = "Usage: PetesAzureChinaBlobTool -{Upload|Delete|Download|List|MakeBlob} -BlobStorageAccountName:<name of Azure Blob Storage> -StorageAccountKey <StorageKey> -BlobContainer <BlobContainer> -FileName <Path to local file> -BlobFileName <Name of Azure Blob file>";
        static int op;
        
        static void Main(string[] args)
        {
            if (args == null)
            {
                Console.WriteLine(usage);
            }
            else
            {
                Dictionary<string, string> dict = CreateDictionaryFromArgs(args);
                bool status = false; 
                if (dict != null)
                {
                    status = CheckDictionaryParameters(dict);                   
                }

                if (!status)
                {
                    Console.WriteLine(usage);

                }
                else
                {
                     switch (op)
                     {
                         case (int) Operation.Download:
                             DownloadFileFromBlobStorage(dict);
                             break;
                         case (int)Operation.Upload:
                             UploadFileFromBlobStorage(dict);
                             break;
                         case (int)Operation.Delete:
                             DeleteFileFromBlobStorage(dict);
                             break;
                         case (int)Operation.List:
                             ListFilesInBlobContainer(dict);
                             break;                        
                         case (int)Operation.MakeBlob:
                             MakeBlob(dict);
                             break;
                          

                     }
                }
            }
            
           
            
        }

        private static void MakeBlob(Dictionary<string, string> dict)
        {
            string url = dict["blobstorageaccountname"];
            string key = dict["storageaccountkey"];
            string containerName = dict["blobcontainer"];

            Uri uri = new Uri(url);

            string account = uri.Host.Substring(0, uri.Host.IndexOf('.'));
            // set the storage account 
            StorageCredentials creds = new StorageCredentials(account, key);

            CloudStorageAccount csa = new CloudStorageAccount(creds, false);
            CloudBlobClient blobStorage = new CloudBlobClient(uri, creds);
            //Azure naming conventions say that container names must be all lower case
            CloudBlobContainer blobContainer = blobStorage.GetContainerReference(containerName.ToLower());
            blobContainer.CreateIfNotExists();
            Console.WriteLine("Blob container " + containerName.ToLower() + " created successfully!");

        }

        private static void ListFilesInBlobContainer(Dictionary<string, string> dict)
        {           
            string url = dict["blobstorageaccountname"];
            string key = dict["storageaccountkey"];
            string containerName = dict["blobcontainer"];

            Uri uri = new Uri(url);

            string account = uri.Host.Substring(0, uri.Host.IndexOf('.'));
            // set the storage account 
            StorageCredentials creds = new StorageCredentials(account, key);

            CloudStorageAccount csa = new CloudStorageAccount(creds, false);
            CloudBlobClient blobStorage = new CloudBlobClient(uri, creds);

            try
            {
                CloudBlobContainer blobContainer = blobStorage.GetContainerReference(containerName);
            
                foreach (var blob in blobContainer.ListBlobs())
                {
                    Console.WriteLine(blob.Uri.AbsolutePath);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString() + " Make sure Blob container exists.");
            }
            
        }

        private static void DeleteFileFromBlobStorage(Dictionary<string, string> dict)
        {
            string url = dict["blobstorageaccountname"];
            string key = dict["storageaccountkey"];
            string containerName = dict["blobcontainer"];
            string blobFileName = dict["blobfilename"];

            
            Uri uri = new Uri(url);
           
            string account = uri.Host.Substring(0, uri.Host.IndexOf('.'));
            // set the storage account 
            StorageCredentials creds = new StorageCredentials(account, key);

            CloudStorageAccount csa = new CloudStorageAccount(creds, false);
            CloudBlobClient blobStorage = new CloudBlobClient(uri, creds);
           
            CloudBlobContainer blobContainer = blobStorage.GetContainerReference(containerName);

            
            // Retrieve reference to a blob 
            CloudBlockBlob blockBlob = blobContainer.GetBlockBlobReference(blobFileName);
            blockBlob.DeleteIfExists();
            Console.WriteLine(blobFileName + " deleted successfully");

        }

        private static void UploadFileFromBlobStorage(Dictionary<string, string> dict)
        {
            string url = dict["blobstorageaccountname"];
            string key = dict["storageaccountkey"];
            string containerName = dict["blobcontainer"];
            string fileName = dict["filename"];
            string blobName = dict["blobfilename"];

            Uri uri = new Uri(url);

            string account = uri.Host.Substring(0, uri.Host.IndexOf('.'));
            // set the storage account 
            StorageCredentials creds = new StorageCredentials(account, key);

            CloudStorageAccount csa = new CloudStorageAccount(creds, false);
            CloudBlobClient blobStorage = new CloudBlobClient(uri, creds);

            CloudBlobContainer blobContainer = blobStorage.GetContainerReference(containerName);


            // Retrieve reference to a blob 
            CloudBlockBlob blockBlob = blobContainer.GetBlockBlobReference(blobName);

            System.Diagnostics.Stopwatch st = new System.Diagnostics.Stopwatch();

            using (var fileStream = System.IO.File.OpenRead(fileName))
            {
                st.Start();
                Console.WriteLine("Uploading file " + fileName);

                blockBlob.UploadFromStream(fileStream);
                st.Stop();
                Console.WriteLine("Upload completed in " + st.ElapsedMilliseconds / 1000 + " seconds");
            }
            
        }

        private static void DownloadFileFromBlobStorage(Dictionary<string, string> dict)
        {
            string url = dict["blobstorageaccountname"];
            string key = dict["storageaccountkey"];
            string blobFileName = dict["blobfilename"];
            string containerName = dict["blobcontainer"];
            string fileName = dict["filename"];

            Uri uri = new Uri(url);

            string account = uri.Host.Substring(0, uri.Host.IndexOf('.'));
            // set the storage account 
            StorageCredentials creds = new StorageCredentials(account, key);

            CloudStorageAccount csa = new CloudStorageAccount(creds, false);
            CloudBlobClient blobStorage = new CloudBlobClient(uri, creds);

            CloudBlobContainer blobContainer = blobStorage.GetContainerReference(containerName);


            // Retrieve reference to a blob 
            CloudBlockBlob blockBlob = blobContainer.GetBlockBlobReference(blobFileName);

            System.Diagnostics.Stopwatch st = new System.Diagnostics.Stopwatch();

            using (var fileStream = System.IO.File.Create(fileName))
            {
                st.Start();
                Console.WriteLine("Downloading file " + fileName);

                blockBlob.DownloadToStream(fileStream);
                st.Stop();
                Console.WriteLine("Download completed in " + st.ElapsedMilliseconds / 1000 + " seconds");
            }
            
        }

        private static bool CheckDictionaryParameters(Dictionary<string, string> dict)
        {
            if (dict.ContainsKey("upload"))
            {
                if (dict.ContainsKey("blobstorageaccountname") && dict.ContainsKey("storageaccountkey") && dict.ContainsKey("blobcontainer") && dict.ContainsKey("filename") && dict.ContainsKey("blobfilename"))
                {
                    op = (int)Operation.Upload;
                    return true;
                }

                else
                {
                    return false;
                }
            }
            else if (dict.ContainsKey("download"))
            {
                if (dict.ContainsKey("blobstorageaccountname") && dict.ContainsKey("storageaccountkey") && dict.ContainsKey("blobcontainer") && dict.ContainsKey("blobfilename") && dict.ContainsKey("filename"))
                {
                    op = (int)Operation.Download;
                    return true;
                }

                else
                {
                    return false;
                }

            }

            else if (dict.ContainsKey("delete"))
            {
                if (dict.ContainsKey("blobstorageaccountname") && dict.ContainsKey("storageaccountkey") && dict.ContainsKey("blobcontainer") && dict.ContainsKey("blobfilename"))
                {
                    op = (int)Operation.Delete;
                    return true;
                }

                else
                {
                    return false;
                }

            }

            else if (dict.ContainsKey("list"))
            {
                if (dict.ContainsKey("blobstorageaccountname") && dict.ContainsKey("storageaccountkey") && dict.ContainsKey("blobcontainer"))
                {
                    op = (int)Operation.List;
                    return true;
                }

                else
                {
                    return false;
                }
            }

            else if (dict.ContainsKey("list"))
            {
                if (dict.ContainsKey("blobstorageaccountname") && dict.ContainsKey("storageaccountkey") && dict.ContainsKey("blobcontainer"))
                {
                    op = (int)Operation.List;
                    return true;
                }

                else
                {
                    return false;
                }
            }
          
            else if (dict.ContainsKey("makeblob"))
            {
                if (dict.ContainsKey("blobstorageaccountname") && dict.ContainsKey("storageaccountkey") && dict.ContainsKey("blobcontainer") && dict.ContainsKey("makeblob"))
                {
                    op = (int)Operation.MakeBlob;
                    return true;
                }

                else
                {
                    return false;
                }
            }

            else return false;
        }

        private static Dictionary<string, string> CreateDictionaryFromArgs(string[] args)
        {
            Dictionary<string, string> dict = null;

            try
            {
                dict = new Dictionary<string, string>();

                foreach (string arg in args)
                {                    
                    if (arg.ToLower().Substring(1) == "list" || arg.ToLower().Substring(1) == "download" || arg.ToLower().Substring(1) == "upload" || arg.ToLower().Substring(1) == "delete" || arg.ToLower().Substring(1) == "makeblob")
                    {
                        dict.Add(arg.Substring(1).ToLower(), null);
                        continue;
                    }
                    //Remove the minus sign
                    string key = arg.Substring(1, arg.IndexOf(":") - 1).ToLower();
                    string value = arg.Substring(arg.IndexOf(":") + 1);
                   
                    dict.Add(key, value);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Supplied arguments were invalid. " + usage);
                
            }
            return dict;
        }

        
    }
    enum Operation 
    {
        Upload, Download, Delete, List, MakeBlob
    }
}
